home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-09-27 | 5.5 KB | 185 lines | [TEXT/CCL2] |
- ;;; File: decl-parser Author: John
-
- (define (parse-decl)
- (let ((decl-type (find-decl-type)))
- (cond ((eq? decl-type 'signdecl)
- (parse-signdecl))
- ((eq? decl-type 'pat-or-op)
- (parse-pat-or-op))
- ((eq? decl-type 'fundef)
- (parse-fundef))
- ((eq? decl-type 'plus-def)
- (parse-plus-def))
- ((eq? decl-type 'annotation)
- (make annotation-decls (annotations (parse-annotations 'decl)))))))
-
- ;;; This looks at the first tokens in a definition to determine it's type.
- ;;; var (:: | ,) - signdecl
- ;;; var apat-start - function definition
- ;;; (var | _) + - definition of infix +
- ;;; anything alse - pattern binding or infix definition
-
- (define (find-decl-type)
- (let* ((saved-excursion (save-scanner-state))
- (decl-type
- (token-case
- (var (scan-var)
- (token-case
- ((\, \:\:) 'signdecl)
- (apat-start 'fundef)
- (+ 'plus-def)
- (else 'pat-or-op)))
- (_ (token-case
- (+ 'plus-def)
- (else 'pat-or-op)))
- (begin-annotation 'annotation)
- (else 'pat-or-op))))
- (restore-excursion saved-excursion)
- decl-type))
-
- ;;; These are the different flavors of decl parsers
-
- (define (parse-signdecl)
- (save-parser-context
- (trace-parser signdecl
- (let ((vars (parse-signdecl-vars)))
- (require-token \:\:
- (signal-missing-token "`::'" "signature declaration"))
- (let ((signature (parse-signature)))
- (make signdecl (vars vars) (signature signature)))))))
-
- (define (parse-signdecl-vars)
- (token-case
- (var (let ((var (var->ast)))
- (token-case (\, (cons var (parse-signdecl-vars)))
- (else (list var)))))
- (else (signal-missing-token "<var>" "signature declaration"))))
-
- (define (parse-pat-or-op)
- (trace-parser patdef
- (let* ((line-number (capture-current-line))
- (pat (parse-pat)))
- (token-case
- (varop (parse-infix-def pat line-number))
- (else (add-rhs pat '() '#f line-number))))))
-
- (define (parse-infix-def pat1 line-number)
- (let* ((op (make var-pat (var (varop->ast))))
- (pat2 (parse-pat)))
- (add-rhs op (list pat1 pat2) '#t line-number)))
-
- (define (parse-fundef)
- (trace-parser fundef
- (let* ((start-line (capture-current-line))
- (fn (parse-apat)) ; must be a single variable
- (args (parse-apat-list)))
- (add-rhs fn args '#f start-line))))
-
- (define (parse-plus-def)
- (trace-parser plus-def
- (let* ((start-line (capture-current-line))
- (var (parse-apat)))
- (parse-infix-def var start-line))))
-
- (define (add-rhs pat args infix? start-line)
- (let* ((rhs (parse-rhs))
- (decls (parse-where-decls))
- (single (make single-fun-def
- (args args)
- (rhs-list rhs)
- (where-decls decls)
- (infix? infix?)))
- (valdef (make valdef (lhs pat) (definitions (list single)))))
- (setf (ast-node-line-number single) start-line)
- (setf (ast-node-line-number valdef) start-line)
- valdef))
-
- (define (parse-rhs)
- (token-case
- (= (let ((rhs (parse-exp)))
- (list (make guarded-rhs (guard (make omitted-guard)) (rhs rhs)))))
- (\| (parse-guarded-rhs))
- (else
- (signal-missing-token "`=' or `|'" "rhs of valdef"))))
-
- (define (parse-guarded-rhs) ; assume just past |
- (trace-parser guard
- (let ((guard (parse-exp-i))) ; 1.2 change
- (require-token = (signal-missing-token "`='" "guarded rhs"))
- (let* ((exp (parse-exp))
- (res (make guarded-rhs (guard guard) (rhs exp))))
- (token-case
- (\| (cons res (parse-guarded-rhs)))
- (else (list res)))))))
-
- (define (parse-where-decls)
- (token-case
- (|where|
- (parse-decl-list))
- (else '())))
-
- (define (parse-decl-list)
- (start-layout (function parse-decl-list-1)))
-
- (define (parse-decl-list-1 in-layout?)
- (token-case
- ((apat-start begin-annotation)
- (let ((decl (parse-decl)))
- (token-case
- (\; (decl-cons decl (parse-decl-list-1 in-layout?)))
- (else (close-layout in-layout?)
- (list decl)))))
- (else
- (close-layout in-layout?)
- '())))
-
- ;;; This adds a new decl to a decl list. Successive decls for the same fn
- ;;; are combined.
-
- (define (decl-cons decl decl-list)
- (cond ((null? decl-list)
- (list decl))
- (else (nconc (combine-decls decl (car decl-list)) (cdr decl-list)))))
-
- (define (decl-push decl decl-stack)
- (cond ((null? decl-stack)
- (list decl))
- (else (nconc (nreverse (combine-decls (car decl-stack) decl))
- (cdr decl-stack)))))
-
- (define (combine-decls decl1 decl2)
- (if (and (is-type? 'valdef decl1)
- (is-type? 'valdef decl2)
- (same-decl-var? (valdef-lhs decl1) (valdef-lhs decl2)))
- (if (eqv? (length (single-fun-def-args (car (valdef-definitions decl1))))
- (length (single-fun-def-args (car (valdef-definitions decl2)))))
- (begin
- (setf (valdef-definitions decl1)
- (nconc (valdef-definitions decl1)
- (valdef-definitions decl2)))
- (list decl1))
- (signal-multiple-definitions-arity-mismatch (valdef-lhs decl1)))
- (list decl1 decl2)))
-
- (define (same-decl-var? pat1 pat2)
- (and (is-type? 'var-pat pat1)
- (is-type? 'var-pat pat2)
- (let ((n1 (var-ref-name (var-pat-var pat1)))
- (n2 (var-ref-name (var-pat-var pat2))))
- (if (eq? n1 n2)
- '#t
- (begin
- (let ((s1 (string-upcase (symbol->string n1)))
- (s2 (string-upcase (symbol->string n2))))
- (when (string=? s1 s2)
- (haskell-warning 'possible-misspelled-function
- "Definitions of ~A and ~A together - maybe one is misspelled" n1 n2))
- '#f))))))
-
- (define (signal-multiple-definitions-arity-mismatch pat)
- (parser-error 'multiple-definitions-arity-mismatch
- "Definition of ~a does not match arity of previous definition."
- pat))
-
-
-